package pos;

import java.awt.*;
import java.util.*;
import pos.utils.XMLConfig;

/**
 * 系统的持久性全局配置对象
 * 它保存了：显示模式(分辨率、色深、是否启用全屏)、音乐音量、音效音量、图形精度、是否启用DDU输出、是否默认自动驾驶模式
 * 它还负责检测当前系统是否支持期望的属性，并避免配置中无法被支持的特性被错误地应用
 * @author plus
 */
public class Profile {

    private DisplayMode Mode;
    private int VolumMusic,  VolumSFX,  GFXLevel;
    private boolean AutoATO,  DDUScreen,  FullScreen;
    private ArrayList<DisplayMode> AvailableModes = new ArrayList<DisplayMode>();
    private boolean FullScreenSupported;

    /**
     * 拷贝构造函数
     * @param target 拷贝源
     */
    public Profile(Profile target) {
        this.VolumMusic = target.VolumMusic;
        this.VolumSFX = target.VolumSFX;
        this.GFXLevel = target.GFXLevel;
        this.AutoATO = target.AutoATO;
        this.DDUScreen = target.DDUScreen;
        this.FullScreen = target.FullScreen;
        this.FullScreenSupported = target.FullScreenSupported;
        this.Mode = new DisplayMode(target.getMode().getWidth(),
                target.getMode().getHeight(), 32,
                target.getMode().getRefreshRate());
        enumGraphicDevices();
    }

    /**
     * 构造函数，从配置路径中的Config.XML读取之前记录的全局配置
     */
    public Profile() {
        this.FullScreenSupported = false;
        load();
        enumGraphicDevices();
        if (this.FullScreen) {
            if (!this.FullScreenSupported) {
                System.err.println("No Full Screen Supported!");
                this.FullScreen = false;
            }
        }

        DisplayMode tempMode;
        boolean isLoadedModeAvailable = false;
        for (int ModesCounter = 0; ModesCounter < this.AvailableModes.size(); ModesCounter++) {
            tempMode = this.AvailableModes.get(ModesCounter);
            if (tempMode.getWidth() == this.Mode.getWidth() &&
                    tempMode.getHeight() == this.Mode.getHeight()) {
                this.Mode = tempMode;
                isLoadedModeAvailable = true;
            }
        }
        if (!isLoadedModeAvailable) {
            System.err.println(
                    "The Mode in XML Configuration is NOT availalbe is this system, " +
                    "the best setting for your system will be appilied!");
            this.Mode = AvailableModes.get(AvailableModes.size() - 1);
            
            /*GraphicsEnvironment environment =
                    GraphicsEnvironment.getLocalGraphicsEnvironment();//通过this对象取得GraphicsDevice
            GraphicsDevice[] device = environment.getScreenDevices();
            this.Mode=device[0].getDisplayMode();*/
        }

        System.out.println("Display Mode set to " + this.Mode.getWidth() + "x" + this.Mode.getHeight() + "@" + this.Mode.getBitDepth());
    }

    /**
     * 构造函数，从参数指定新的全局配置，并将其写入配置路径中的Config.XML
     * @param DisplayMode 新的显示模式
     * @param VolumMusic 新的音乐音量
     * @param VolumSFX 新的音效音量
     * @param GFXLevel 新的图形精细度
     * @param AutoATO 新的默认自动驾驶启用情况
     * @param DDUScreen 新的DDU屏幕输出情况
     * @param FullScreen 新的全屏模式启用情况
     */
    public Profile(DisplayMode DisplayMode, int VolumMusic, int VolumSFX, int GFXLevel, boolean AutoATO, boolean DDUScreen, boolean FullScreen) {
        this.Mode = DisplayMode;
        this.VolumMusic = VolumMusic;
        this.VolumSFX = VolumSFX;
        this.GFXLevel = GFXLevel;
        this.AutoATO = AutoATO;
        this.DDUScreen = DDUScreen;
        this.FullScreen = FullScreen;
        this.FullScreenSupported = false;
        save();
        enumGraphicDevices();
    }

    public boolean isAutoATO() {
        return AutoATO;
    }

    public boolean isDDUScreen() {
        return DDUScreen;
    }

    public int getGFXLevel() {
        return GFXLevel;
    }

    public DisplayMode getMode() {
        return Mode;
    }

    public int getVolumMusic() {
        return VolumMusic;
    }

    public int getVolumSFX() {
        return VolumSFX;
    }

    public boolean isFullScreen() {
        return FullScreen;
    }

    public void setData(Profile target) {
        this.VolumMusic = target.VolumMusic;
        this.VolumSFX = target.VolumSFX;
        this.GFXLevel = target.GFXLevel;
        this.AutoATO = target.AutoATO;
        this.DDUScreen = target.DDUScreen;
        this.FullScreen = target.FullScreen;
        this.FullScreenSupported = target.FullScreenSupported;
        this.Mode = new DisplayMode(target.getMode().getWidth(),
                target.getMode().getHeight(), 32,
                target.getMode().getRefreshRate());
        enumGraphicDevices();
    }

    private void enumGraphicDevices() {
        GraphicsEnvironment environment =
                GraphicsEnvironment.getLocalGraphicsEnvironment();//通过this对象取得GraphicsDevice
        GraphicsDevice[] device = environment.getScreenDevices();
        DisplayMode[] gdm;
        DisplayMode dmCurrent;
        for (int i = 0; i < device.length; i++) {
            this.FullScreenSupported = device[i].isFullScreenSupported();
            gdm = device[i].getDisplayModes();
            dmCurrent = device[i].getDisplayMode();
            for (int j = 0; j < gdm.length; j++) {
                DisplayMode dm = gdm[j];
                if ((dm.getWidth() > dm.getHeight()) && (dm.getWidth() <= dm.getHeight() * 1.6) && (dm.getWidth() >= 800) && (dm.getHeight() >= 600) && (dm.getRefreshRate() == dmCurrent.getRefreshRate()) && (dm.getBitDepth() == 32)) {
                    this.AvailableModes.add(dm);
                //System.out.println(gdm[j].getWidth()+"x"+gdm[j].getHeight()+"@"+dm.getBitDepth()+"bits");
                }
            }

        }
    }

    private void load() {
        XMLConfig xmlConfig = new XMLConfig();
        this.Mode = new DisplayMode(Integer.parseInt(xmlConfig.getData("width")),
                Integer.parseInt(xmlConfig.getData("height")),
                Integer.parseInt(xmlConfig.getData("colorbits")),
                60);
        this.VolumMusic = Integer.parseInt(xmlConfig.getData("VMusic"));
        this.VolumSFX = Integer.parseInt(xmlConfig.getData("VSFX"));
        this.GFXLevel = Integer.parseInt(xmlConfig.getData("GFXLevel"));
        this.AutoATO = stringToBoolean(xmlConfig.getData("AutoATO"));
        this.DDUScreen = stringToBoolean(xmlConfig.getData("DDUScreen"));
        this.FullScreen = stringToBoolean(xmlConfig.getData("FullScreen"));
        System.out.println(String.valueOf(this.AutoATO) + String.valueOf(this.DDUScreen) + String.valueOf(this.FullScreen));
    }

    public ArrayList<DisplayMode> getAvailableModes() {
        return AvailableModes;
    }

    public boolean isFullScreenSupported() {
        return FullScreenSupported;
    }

    public void save() {
        XMLConfig xmlConfig = new XMLConfig();
        xmlConfig.setData("width", String.valueOf(this.Mode.getWidth()));
        xmlConfig.setData("height", String.valueOf(this.Mode.getHeight()));
        xmlConfig.setData("colorbits", String.valueOf(this.Mode.getBitDepth()));
        xmlConfig.setData("VMusic", String.valueOf(this.VolumMusic));
        xmlConfig.setData("VSFX", String.valueOf(this.VolumSFX));
        xmlConfig.setData("GFXLevel", String.valueOf(this.GFXLevel));
        xmlConfig.setData("AutoATO", booleanToString(this.AutoATO));
        xmlConfig.setData("DDUScreen", booleanToString(this.DDUScreen));
        xmlConfig.setData("FullScreen", booleanToString(this.FullScreen));

    }

    public void setAutoATO(boolean AutoATO) {
        this.AutoATO = AutoATO;
    }

    public void setAvailableModes(ArrayList<DisplayMode> AvailableModes) {
        this.AvailableModes = AvailableModes;
    }

    public void setDDUScreen(boolean DDUScreen) {
        this.DDUScreen = DDUScreen;
    }

    public void setFullScreen(boolean FullScreen) {
        this.FullScreen = FullScreen;
    }

    public void setFullScreenSupported(boolean FullScreenSupported) {
        this.FullScreenSupported = FullScreenSupported;
    }

    public void setGFXLevel(int GFXLevel) {
        this.GFXLevel = GFXLevel;
    }

    public void setMode(DisplayMode Mode) {
        this.Mode = Mode;
    }

    public void setVolumMusic(int VolumMusic) {
        this.VolumMusic = VolumMusic;
    }

    public void setVolumSFX(int VolumSFX) {
        this.VolumSFX = VolumSFX;
    }

    private String booleanToString(boolean bool) {
        if (bool) {
            return "1";
        } else {
            return "0";
        }
    }

    private boolean stringToBoolean(String str) {
        if (str.equals("0")) {
            return false;
        } else {
            return true;
        }
    }
}
